﻿Public Class mapGenerator
    Shared map(,) As Integer
    Shared collisionMap(,) as Integer
    Shared random As Random
    Shared dungeon() As Room

    Shared maxRoomSize = 10
    Shared mapMaxX As Integer
    Shared mapMaxY As Integer

    Shared WallTile As Integer = 1
    Shared FloorTile As Integer = 2
  
    Class Room
        Dim width As Integer
        Dim height As Integer
        Dim xCoord As Integer
        Dim yCoord As Integer

        Public Sub New(w, h, x, y)
            width = w
            height = h
            xCoord = x
            yCoord = y

            drawRoom()
        End Sub

        Private Sub drawRoom()
            For i As Integer = xCoord To width + xCoord
                If i = xCoord Or i = xCoord + width Then
                    For j As Integer = yCoord To height + yCoord
                        map(i, j) = WallTile
                        collisionMap(i,j) = 1
                    Next
                Else
                    For j As Integer = yCoord To height + yCoord
                        If j = yCoord Or j = height + yCoord Then
                            map(i, j) = WallTile
                            collisionMap(i,j) = 1
                        Else
                            map(i, j) = FloorTile
                        End If
                    Next
                End If
            Next
        End Sub
        Public Function getHeight() As Integer
            Return height
        End Function
        Public Function getWidth() As Integer
            Return width
        End Function
        Public Function getXCoord() As Integer
            Return xCoord
        End Function
        Public Function getYCoord() As Integer
            Return yCoord
        End Function
        Public Overrides Function ToString() As String
            Return "Width: " & width & " Height: " & height & " at (" & xCoord & ", " & yCoord & ")"
        End Function
    End Class

    Shared Function GenerateDungeonMap(ByRef dungeonMap As Integer(,), ByRef dungeonRooms As Room(), ByRef collisionArray As Integer(,)) As Integer(,)
        map = dungeonMap
        collisionMap = collisionArray
        random = New Random
        ReDim dungeon(map.GetLength(0) / 3)
        Dim room As Room = Nothing
        mapMaxX = map.GetLength(0) - 1
        mapMaxY = map.GetLength(1) - 1

        Console.WriteLine("Number of rooms: " & dungeon.Length)
        Console.WriteLine("Size of map: " & mapMaxX & ", " & mapMaxY)
        'Draw spawn room
        room = New Room(7, 7, 0, mapMaxY - maxRoomSize)
        dungeon(0) = room

        For i As Integer = 1 To dungeon.Length - 1
            room = generateRoom(i)
            dungeon(i) = room
            generateHallway(i)
        Next

        'Add Treasure Chest
        Dim chestPlaced As Boolean = False
        Dim chestX As Integer
        Dim chestY As Integer

        While Not chestPlaced
            chestX = random.Next(map.GetLength(0))
            chestY = random.Next(map.GetLength(1))

            If map(chestX, chestY) = 2 Then
                map(chestX, chestY) = 3
                Console.WriteLine("Putting chest at (" & chestX & "," & chestY & ")")
                chestPlaced = True
            End If
        End While

        Return map
    End Function

    Private Shared Function generateRoom(ByVal roomNo As Integer) As Room
        Dim xSize As Integer = random.Next(5, maxRoomSize + 1)
        Dim ySize As Integer = random.Next(5, maxRoomSize + 1)

        Dim xPos As Integer = dungeon(roomNo - 1).getXCoord() + dungeon(roomNo - 1).getWidth()
        Dim yPos As Integer = dungeon(roomNo - 1).getYCoord()
        'Dim xCoord As Integer = random.Next(0, map.GetLength(0) - xSize)
        'Dim yCoord As Integer = random.Next(0, map.GetLength(1) - ySize)

        'Only gerates rooms to the right of spawn, until edge of map is reached
        Dim xCoord As Integer = random.Next(xPos, xPos + maxRoomSize)
        Dim yCoord As Integer = yPos

        'See if room fits in space left
        If (xCoord + xSize <= mapMaxX) Then
            'See if room goes off of map
            If (yCoord + ySize <= mapMaxY) Then
                Dim room = New Room(xSize, ySize, xCoord, yCoord)
                Console.WriteLine("Generating room " & room.ToString)
                Return room
            Else
                'Room doesn't fit, forcing different size
                Dim overflow = mapMaxY - ySize
                ySize = ySize - overflow
                Dim room = New Room(xSize, ySize, xCoord, yCoord)
                Console.WriteLine("Room doesnt fit on Y axis " & room.ToString)
                Return room
            End If
        Else
            'Room didn't fit, forcing different size
            If yCoord - maxRoomSize < 0 Then
                Console.WriteLine("Room doesn't fit. Finished generating dungeon.")
                Return New Room(0, 0, 0, 0)
            Else
                Dim room = New Room(xSize, ySize, 0, yCoord - maxRoomSize)
                Console.WriteLine("Room doesnt fit on X axis " & room.ToString)
                Return room
            End If
        End If
    End Function

    Private Shared Sub generateHallway(roomNo As Integer)
        Dim roomA = dungeon(roomNo)
        Dim roomB = dungeon(roomNo - 1)
        Dim newWidth_ As Integer
        Dim newHeight As Integer
        Dim newXCoord As Integer
        Dim newYCoord As Integer

        ''If we jumped up a row during map generation
        If roomA.getXCoord < roomB.getXCoord Then
            'Draw path from row below
            Console.WriteLine("Room A is on a different line from room B.")
            For i As Integer = roomNo - 1 To 0 Step -1
                Console.WriteLine("Testing room " & dungeon(i).ToString)
                If dungeon(i).getXCoord = 0 Then
                    roomB = dungeon(i)
                    Console.WriteLine("Found room " & roomB.ToString)
                    Exit For
                End If
            Next

            'RoomB should be directly below RoomA, draw hallway down from A.
            newWidth_ = 3
            newHeight = roomB.getYCoord - (roomA.getYCoord + roomA.getHeight)
            newXCoord = roomB.getXCoord + 2
            newYCoord = roomA.getYCoord + roomA.getHeight

            Console.WriteLine("Generating vertical hallway from Y: " & newYCoord & " to " & newYCoord + newHeight & " at X: " & newYCoord)
            Dim room = New Room(newWidth_, newHeight, newXCoord, newYCoord)

            map(newXCoord + 1, newYCoord) = FloorTile
            collisionMap(newXCoord + 1, newYCoord) = 0
            map(newXCoord + 2, newYCoord) = FloorTile
            collisionMap(newXCoord + 2, newYCoord) = 0
            map(newXCoord + 1, newYCoord + newHeight) = FloorTile
            collisionMap(newXCoord + 1, newYCoord + newHeight) = 0
            map(newXCoord + 2, newYCoord + newHeight) = FloorTile
            collisionMap(newXCoord + 2, newYCoord + newHeight) = 0

        Else
            'No jump. Go from room on left (Should be room B)
            newWidth_ = roomA.getXCoord - (roomB.getXCoord + roomB.getWidth)
            newHeight = 3
            newXCoord = roomB.getXCoord + roomB.getWidth
            newYCoord = roomB.getYCoord + (roomB.getHeight / 4)

            If newYCoord <= 0 Then
                newYCoord = roomB.getYCoord + 2
            End If

            Console.WriteLine("Generating hallway from X: " & newXCoord & " to " & newXCoord + newWidth_ & " at Y: " & newYCoord)
            Dim room = New Room(newWidth_, newHeight, newXCoord, newYCoord)

            map(newXCoord, newYCoord + 1) = FloorTile
            collisionMap(newXCoord, newYCoord + 1) = 0
            map(newXCoord, newYCoord + 2) = FloorTile
            collisionMap(newXCoord, newYCoord + 2) = 0
            map(newXCoord + newWidth_, newYCoord + 1) = FloorTile
            collisionMap(newXCoord + newWidth_, newYCoord + 1) = 0
            map(newXCoord + newWidth_, newYCoord + 2) = FloorTile
            collisionMap(newXCoord + newWidth_, newYCoord + 2) = 0
        End If
    End Sub
End Class
